package GUILayer;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.GroupLayout.Alignment;
import javax.swing.border.Border;

import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;

import ControlLayer.PersonCtr;
import ControlLayer.PersonException;
import ControlLayer.RoomBookingCtr;
import ControlLayer.RoomBookingException;
import ControlLayer.RoomTypeCtr;
import ControlLayer.SaleCtr;
import ControlLayer.SaleException;
import GUIHelper.CheckInFrame;
import GUIHelper.CheckOutFrame;

import ModelLayer.Guest;
import ModelLayer.KeyWord;
import ModelLayer.Room;
import ModelLayer.RoomBooking;
import ModelLayer.RoomBookingLine;
import ModelLayer.RoomType;
import ModelLayer.Sale;

public class SaleGUI extends JPanel implements ActionListener {
	private static final long serialVersionUID = 1L;
	private JTable saleTable;
	private JTable rbTable;
	// private JTable acTable;
	private DefaultTableModel saleTableModel;
	private DefaultTableModel rbTableModel;
	// private DefaultTableModel acTableModel;
	private JScrollPane saleScrollPane;
	private JScrollPane rbScrollPane;
	// private JScrollPane acScrollPane;

	private JTextField search;
	private JTextField textField_saleId;
	private JTextField textField_guestId;
	private JTextField textField_employeeId;
	private JTextField textField_saleCreateDate;
	private JTextField textField_salePayDate;
	private JTextField textField_salePayStatus;
	private JTextField textField_salePayMethod;
	private JTextField textField_salePrice;

	private JTextField textField_rbCreateDate;
	private JTextField textField_rbStartDate;
	private JTextField textField_rbEndDate;
	private JTextField textField_rbDeposit;
	private JTextField textField_rbRent;
	private JTextField textField_rbPayStatus;
	private JTextField textField_rtId;
	private JTextField textField_rtQuantity;

	private JComboBox<String> jcbsalePayStatus;
	private JComboBox<String> jcbrbPayStatus;
	private JComboBox<String> jcbsalePayMethod;
	private String[] listStringsSale = { KeyWord.SaleUnpaid.toString(),
			KeyWord.SalePaid.toString() };
	private String[] listStringsRB = { KeyWord.DepositUnpaid.toString(),
			KeyWord.DepositPaid.toString(), KeyWord.RentPaid.toString() };
	private String[] listStringsPayMethod = { "None",
			KeyWord.CreditCard.toString(), KeyWord.Cash.toString() };

	private JPanel allSalePanel;
	private JPanel rbTablePanel;

	private SaleCtr saleCtr;
	private RoomBookingCtr roomBookingCtr;
	private PersonCtr personCtr;
	private RoomTypeCtr rtCtr;

	private HashMap<Integer, Integer> roomBookingLines;
	private int totalPrice;
	private JPanel saleGUI;

	public SaleGUI() {
		saleGUI = this;
		saleCtr = new SaleCtr();
		personCtr = new PersonCtr();
		rtCtr = new RoomTypeCtr();
		roomBookingCtr = new RoomBookingCtr();
		roomBookingLines = new HashMap<Integer, Integer>();
		initialize();
	}

	public void initialize() {
		this.setLayout(new BorderLayout());

		allSalePanel = new JPanel();
		allSalePanel.setBorder(BorderFactory.createTitledBorder("All Sales"));
		allSalePanel.setLayout(new BorderLayout());

		JPanel salePanel = new JPanel();
		salePanel.setBorder(BorderFactory.createTitledBorder("Sale"));
		salePanel.setLayout(new BoxLayout(salePanel, BoxLayout.Y_AXIS));

		this.add(allSalePanel, BorderLayout.WEST);
		this.add(salePanel, BorderLayout.CENTER);

		// add whole sales table
		JPanel searchPanel = new JPanel();
		search = new JTextField();

		search.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent arg0) {
				showAllSale();
			}
		});

		searchPanel.add(search);
		search.setColumns(70);
		allSalePanel.add(searchPanel, BorderLayout.NORTH);

		GroupLayout gl_searchPanel = new GroupLayout(searchPanel);
		gl_searchPanel.setHorizontalGroup(gl_searchPanel.createParallelGroup(
				Alignment.LEADING).addComponent(search));
		gl_searchPanel.setVerticalGroup(gl_searchPanel.createParallelGroup(
				Alignment.LEADING).addGroup(
				gl_searchPanel
						.createSequentialGroup()
						.addGap(5)
						.addComponent(search, GroupLayout.PREFERRED_SIZE,
								GroupLayout.DEFAULT_SIZE,
								GroupLayout.PREFERRED_SIZE)));
		searchPanel.setLayout(gl_searchPanel);

		addSaleTable();
		showAllSale();

		// add sale info panel
		JPanel saleInfoPanel = new JPanel();
		salePanel.add(saleInfoPanel);
		GroupLayout gl = new GroupLayout(saleInfoPanel);
		saleInfoPanel.setLayout(gl);

		Border color2 = BorderFactory.createLineBorder(Color.DARK_GRAY);
		// Border raisedetched2 = BorderFactory
		// .createEtchedBorder(EtchedBorder.RAISED);
		TitledBorder title2;
		title2 = BorderFactory.createTitledBorder(color2, "Sale Info");
		saleInfoPanel.setBorder(title2);

		gl.setAutoCreateGaps(true);
		gl.setAutoCreateContainerGaps(true);

		JLabel lblsaleId = new JLabel("Sale Id: ");
		JLabel lblguestId = new JLabel("Guest Id: ");
		JLabel lblemployeeId = new JLabel("Employee Id: ");
		JLabel lblcreateDate = new JLabel("Create Date(dd/mm/yyyy): ");
		JLabel lblpayDate = new JLabel("Pay Date(dd/mm/yyyy): ");
		JLabel lblprice = new JLabel("Total Price: ");
		JLabel lblpayMethod = new JLabel("Pay Method: ");
		JLabel lblpayStatus = new JLabel("Pay Status: ");
		textField_saleId = new JTextField();
		textField_saleId.setEditable(false);
		textField_employeeId = new JTextField();
		textField_saleCreateDate = new JTextField();
		textField_saleCreateDate.setText(new SimpleDateFormat("dd/MM/yyyy")
				.format(Calendar.getInstance().getTime()));
		textField_salePayDate = new JTextField();
		textField_salePayMethod = new JTextField();
		textField_salePrice = new JTextField();
		textField_guestId = new JTextField();
		textField_salePayStatus = new JTextField();

		jcbsalePayStatus = new JComboBox<String>(listStringsSale);
		jcbsalePayStatus.setSelectedIndex(0);
		jcbsalePayStatus.addActionListener(this);

		jcbsalePayMethod = new JComboBox<String>(listStringsPayMethod);
		jcbsalePayMethod.setSelectedIndex(0);
		jcbsalePayMethod.addActionListener(this);

		gl.setHorizontalGroup(gl
				.createSequentialGroup()
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(lblsaleId)
								.addComponent(lblemployeeId)
								.addComponent(lblcreateDate)
								.addComponent(lblpayDate))
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(textField_saleId)
								.addComponent(textField_employeeId)
								.addComponent(textField_saleCreateDate)
								.addComponent(textField_salePayDate))
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(lblguestId)
								.addComponent(lblprice)
								.addComponent(lblpayStatus)
								.addComponent(lblpayMethod))
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(textField_guestId)
								.addComponent(textField_salePrice)
								.addComponent(jcbsalePayStatus)
								.addComponent(jcbsalePayMethod)));
		gl.setVerticalGroup(gl
				.createSequentialGroup()
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(lblsaleId)
								.addComponent(textField_saleId)
								.addComponent(lblguestId)
								.addComponent(textField_guestId))
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(lblemployeeId)
								.addComponent(textField_employeeId)
								.addComponent(lblprice)
								.addComponent(textField_salePrice))
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(lblcreateDate)
								.addComponent(textField_saleCreateDate)
								.addComponent(lblpayStatus)
								.addComponent(jcbsalePayStatus))
				.addGroup(
						gl.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(lblpayDate)
								.addComponent(textField_salePayDate)
								.addComponent(lblpayMethod)
								.addComponent(jcbsalePayMethod)));

		// add room booking Info
		JPanel rbPanel = new JPanel();
		rbPanel.setLayout(new BoxLayout(rbPanel, BoxLayout.Y_AXIS));
		salePanel.add(rbPanel);

		Border color = BorderFactory.createLineBorder(Color.DARK_GRAY);
		// Border raisedetched = BorderFactory
		// .createEtchedBorder(EtchedBorder.RAISED);
		TitledBorder title;
		title = BorderFactory.createTitledBorder(color, "Room Booking");
		rbPanel.setBorder(title);

		JLabel lblrbSDate = new JLabel("Start Date(dd/mm/yyyy): ");
		JLabel lblrbEDate = new JLabel("End Date(dd/mm/yyyy): ");
		JLabel lblrbDeposit = new JLabel("Deposit: ");
		JLabel lblrbRent = new JLabel("Rent: ");
		JLabel lblrbPStatus = new JLabel("Pay Status: ");
		JLabel lblrbCDate = new JLabel("Create Date(dd/mm/yyyy)");

		textField_rbCreateDate = new JTextField();
		textField_rbCreateDate.setText(new SimpleDateFormat("dd/MM/yyyy")
				.format(Calendar.getInstance().getTime()));
		textField_rbDeposit = new JTextField();
		textField_rbEndDate = new JTextField();
		textField_rbPayStatus = new JTextField();
		textField_rbRent = new JTextField();
		textField_rbStartDate = new JTextField();

		jcbrbPayStatus = new JComboBox<String>(listStringsRB);
		jcbrbPayStatus.setSelectedIndex(0);
		jcbrbPayStatus.addActionListener(this);

		JPanel rbInfoPanel = new JPanel();
		rbPanel.add(rbInfoPanel);

		GroupLayout gl2 = new GroupLayout(rbInfoPanel);
		rbInfoPanel.setLayout(gl2);
		// rbInfoPanel.setBorder(BorderFactory.createTitledBorder("RoomBooking Info"));
		gl2.setAutoCreateGaps(true);
		gl2.setAutoCreateContainerGaps(true);

		gl2.setHorizontalGroup(gl2
				.createSequentialGroup()
				.addGroup(
						gl2.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(lblrbSDate)
								.addComponent(lblrbDeposit)
								.addComponent(lblrbCDate))
				.addGroup(
						gl2.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(textField_rbStartDate)
								.addComponent(textField_rbDeposit)
								.addComponent(textField_rbCreateDate))
				.addGroup(
						gl2.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(lblrbEDate)
								.addComponent(lblrbRent)
								.addComponent(lblrbPStatus))
				.addGroup(
						gl2.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(textField_rbEndDate)
								.addComponent(textField_rbRent)
								.addComponent(jcbrbPayStatus)));
		gl2.setVerticalGroup(gl2
				.createSequentialGroup()
				.addGroup(
						gl2.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(lblrbSDate)
								.addComponent(textField_rbStartDate)
								.addComponent(lblrbEDate)
								.addComponent(textField_rbEndDate))
				.addGroup(
						gl2.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(lblrbDeposit)
								.addComponent(textField_rbDeposit)
								.addComponent(lblrbRent)
								.addComponent(textField_rbRent))
				.addGroup(
						gl2.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(lblrbCDate)
								.addComponent(textField_rbCreateDate)
								.addComponent(lblrbPStatus)
								.addComponent(jcbrbPayStatus)));

		// add room booking table
		rbTablePanel = new JPanel();
		rbTablePanel.setLayout(new BoxLayout(rbTablePanel, BoxLayout.Y_AXIS));
		rbPanel.add(rbTablePanel);

		addRBTable();
		// showRBTable(Integer.parseInt(textField_saleId.getText()));

		// add room booking choice buttons panel
		JPanel rbChoicePanel = new JPanel();
		rbChoicePanel.setLayout(new FlowLayout());
		rbTablePanel.add(rbChoicePanel);

		JButton btnAdd = new JButton("Add");
		JButton btnRBDelete = new JButton("Delete");
		JButton btnCheckIn = new JButton("Check In");
		JButton btnCheckOut = new JButton("Check Out");
		JButton btnCancelRB = new JButton("Cancel Roombooking");

		rbChoicePanel.add(btnAdd);
		rbChoicePanel.add(btnRBDelete);
		rbChoicePanel.add(btnCheckIn);
		rbChoicePanel.add(btnCheckOut);
		rbChoicePanel.add(btnCancelRB);

		btnCancelRB.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				RoomBooking rb = roomBookingCtr.getRoomBooking(Integer
						.parseInt(textField_saleId.getText()));
				Calendar cal1 = Calendar.getInstance();
				Calendar cal2 = Calendar.getInstance();
				cal2.setTime(rb.getStartDate());
				cal1.setTime(Calendar.getInstance().getTime());
				if (textField_saleId.getText().isEmpty()) {
					JOptionPane.showMessageDialog(null, "Please select a sale",
							"Error", JOptionPane.ERROR_MESSAGE);
				} else {
					// TODO

					double refundPrice = 0;

					int days = daysBetween(cal1, cal2);

					if (days >= 14) {
						refundPrice = rb.getRent() * RoomBooking.getHalfRate();
						saleCtr.updateSalePrice(
								Integer.parseInt(textField_saleId.getText()),
								Double.parseDouble(textField_salePrice
										.getText()) - refundPrice);
						roomBookingCtr.deleteRoomBooking(Integer
								.parseInt(textField_saleId.getText()));
						JOptionPane.showMessageDialog(null,
								"Roombooking is canceled",
								"Cancel Roombooking",
								JOptionPane.INFORMATION_MESSAGE);
						cleanTextField();
						showAllSale();
					} else if (days >= 7) {
						refundPrice = rb.getRent()
								* RoomBooking.getQuaterRate();
						saleCtr.updateSalePrice(
								Integer.parseInt(textField_saleId.getText()),
								Double.parseDouble(textField_salePrice
										.getText()) - refundPrice);
						roomBookingCtr.deleteRoomBooking(Integer
								.parseInt(textField_saleId.getText()));
						JOptionPane.showMessageDialog(null,
								"Roombooking is canceled",
								"Cancel Roombooking",
								JOptionPane.INFORMATION_MESSAGE);
						cleanTextField();
						showAllSale();
					} else {
						JOptionPane.showMessageDialog(null,
								"Roombooking can not be canceled",
								"Cancel Roombooking",
								JOptionPane.INFORMATION_MESSAGE);
					}

				}

			}
		});

		btnAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// TODO
				if (!textField_saleId.getText().isEmpty()) {
					if (!isAbleToEdit(Integer.parseInt(textField_saleId
							.getText()))) {
						JOptionPane
								.showMessageDialog(
										null,
										"Some rooms have been checked in, roombookingline is not available for editting",
										"Error", JOptionPane.ERROR_MESSAGE);
					} else {
						JFrame addSalelineFrame = addSalelinePopupWindow();
						addSalelineFrame.setVisible(true);
					}
				} else {
					JFrame addSalelineFrame = addSalelinePopupWindow();
					addSalelineFrame.setVisible(true);
				}

			}
		});

		btnRBDelete.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (roomBookingLines.size() == 0) {
					JOptionPane.showMessageDialog(null,
							"There is nothing to delete", "Error",
							JOptionPane.ERROR_MESSAGE);
				} else if (!textField_saleId.getText().isEmpty()) {
					if (!isAbleToEdit(Integer.parseInt(textField_saleId
							.getText()))) {
						JOptionPane
								.showMessageDialog(
										null,
										"Some rooms have been checked in, roombookingline is not available for editting",
										"Error", JOptionPane.ERROR_MESSAGE);
					} else {
						JFrame addSalelineFrame = addSalelinePopupWindow();
						addSalelineFrame.setVisible(true);
					}
				} else {
					JFrame deleteSalelineFrame = deleteSalelinePopupWindow();
					deleteSalelineFrame.setVisible(true);
				}
			}
		});

		btnCheckIn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (textField_saleId.getText().isEmpty()) {
					JOptionPane.showMessageDialog(null, "Please select a sale",
							"Error", JOptionPane.ERROR_MESSAGE);
				} else {
					CheckInFrame checkInFrame = new CheckInFrame(saleGUI,
							Integer.parseInt(textField_saleId.getText()));
					checkInFrame.getFrame().setVisible(true);
				}
			}
		});
		//TODO
		btnCheckOut.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (textField_saleId.getText().isEmpty()) {
					JOptionPane.showMessageDialog(null, "Please select a sale",
							"Error", JOptionPane.ERROR_MESSAGE);
				} else {
					CheckOutFrame checkOutFrame = new CheckOutFrame(saleGUI,
							Integer.parseInt(textField_saleId.getText()));
					checkOutFrame.getFrame().setVisible(true);
				}
			}
		});

		// add sale choice buttons panel
		JPanel saleChoicePanel = new JPanel();
		saleChoicePanel.setLayout(new FlowLayout());
		salePanel.add(saleChoicePanel);

		JButton btnCreate = new JButton("Create");
		JButton btnSave = new JButton("Save");
		JButton btnDelete = new JButton("Delete");
		JButton btnClear = new JButton("Clear");

		saleChoicePanel.add(btnCreate);
		saleChoicePanel.add(btnSave);
		saleChoicePanel.add(btnDelete);
		saleChoicePanel.add(btnClear);

		btnCreate.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (!textField_saleId.getText().isEmpty()) {
					JOptionPane.showMessageDialog(null,
							"Please clear current fields before create sale",
							"Error", JOptionPane.ERROR_MESSAGE);
				} else {
					try {
						// TODO
						// set sale info
						Sale sale = new Sale();
						sale.setCreateDate(Calendar.getInstance().getTime());
						sale.setPayStatus(KeyWord
								.valueOf(listStringsSale[jcbsalePayStatus
										.getSelectedIndex()]));

						if (!textField_salePayDate.getText().isEmpty())
							sale.setPayDate(new SimpleDateFormat("dd/MM/yyyy")
									.parse(textField_salePayDate.getText()));

						if (jcbsalePayMethod.getSelectedIndex() != 0)
							sale.setPayMethod(KeyWord
									.valueOf(listStringsPayMethod[jcbsalePayMethod
											.getSelectedIndex()]));

						// check if employee exist
						sale.setEmployee(personCtr.getEmployee(Integer
								.parseInt(textField_employeeId.getText())));

						// check if guest exist
						sale.setGuest((Guest) personCtr.getGuest(Integer
								.parseInt(textField_guestId.getText())));

						// set room booking info
						RoomBooking rb = new RoomBooking();
						rb.setCreateDate(Calendar.getInstance().getTime());
						rb.setStartDate(new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbStartDate.getText()));
						rb.setEndDate(new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbEndDate.getText()));
						rb.setPayStatus(KeyWord
								.valueOf(listStringsRB[jcbrbPayStatus
										.getSelectedIndex()]));

						Date startDate = new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbStartDate.getText());
						Date endDate = new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbEndDate.getText());
						Date currentDate = Calendar.getInstance().getTime();
						Calendar c = Calendar.getInstance();
						c.setTime(currentDate);
						c.add(Calendar.DAY_OF_MONTH, -1);
						Date dateBefore = c.getTime();
						if (startDate.after(endDate)) {
							JOptionPane
									.showMessageDialog(
											null,
											"Input start date value should be before end date",
											"Error", JOptionPane.ERROR_MESSAGE);
						} else if (startDate.before(dateBefore)) {
							JOptionPane.showMessageDialog(null,
									"Input start date is before current date",
									"Error", JOptionPane.ERROR_MESSAGE);
						} else {
							// calculate rent
							int days = calculateDatesForRB();
							double rent = 0;
							if (roomBookingLines.size() != 0) {
								LinkedList<RoomBookingLine> lines = new LinkedList<RoomBookingLine>();
								Set<Integer> rtIds = roomBookingLines.keySet();
								for (Integer rtId : rtIds) {
									RoomBookingLine line = new RoomBookingLine();
									RoomType rt = rtCtr.getRoomType(rtId);
									line.setRoomType(rt);
									line.setQuantity(roomBookingLines.get(rtId));
									line.setTotalPrice(rt.getPricePerNight()
											* roomBookingLines.get(rtId) * days);// set
																					// price
									lines.add(line);
								}
								// add room booking line
								for (RoomBookingLine line : lines) {
									rent += line.getRoomType()
											.getPricePerNight()
											* line.getQuantity() * days;
								}
								// set roombookinglines
								rb.setLines(lines);
							}

							rb.setRent(rent);
							rb.setDeposit(rent * RoomBooking.getHalfRate());

							// set sale price and room booking
							sale.setTotalPrice(rent);
							sale.setRoomBooking(rb);
							if (saleCtr.createSale(sale))
								JOptionPane.showMessageDialog(null,
										"The sale is created", "Create Sale",
										JOptionPane.INFORMATION_MESSAGE);
							else
								JOptionPane
										.showMessageDialog(
												null,
												"Fail to create sale because of incorrect values",
												"Create Sale",
												JOptionPane.INFORMATION_MESSAGE);
							cleanTextField();
							showAllSale();
						}
					} catch (PersonException a) {
						JOptionPane.showMessageDialog(null,
								a.getPersonException(), "Error",
								JOptionPane.ERROR_MESSAGE);

					} catch (RoomBookingException a) {
						JOptionPane.showMessageDialog(null,
								a.getBookingException(), "Error",
								JOptionPane.ERROR_MESSAGE);

					} catch (ParseException e1) {
						JOptionPane.showMessageDialog(null,
								"Please input correct date format", "Error",
								JOptionPane.ERROR_MESSAGE);
					} catch (Exception ex) {
						JOptionPane.showMessageDialog(null,
								"Please input correct values", "Error",
								JOptionPane.ERROR_MESSAGE);
					}

				}

			}
		});

		btnDelete.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (textField_saleId.getText().isEmpty()) {
					JOptionPane.showMessageDialog(null, "Please select a sale",
							"Error", JOptionPane.ERROR_MESSAGE);
				} else {
					int reply = JOptionPane.showConfirmDialog(null,
							"Do you want to delete this sale ?", "Delete Sale",
							JOptionPane.YES_NO_OPTION,
							JOptionPane.WARNING_MESSAGE);
					if (reply == JOptionPane.YES_OPTION) {
						try {
							saleCtr.deleteSale(Integer
									.parseInt(textField_saleId.getText()));
							JOptionPane.showMessageDialog(null,
									"The sale is deleted", "Delete Sale",
									JOptionPane.INFORMATION_MESSAGE);
							showAllSale();
							cleanTextField();
						} catch (Exception c) {
							JOptionPane.showMessageDialog(null,
									"Fail to delete sale", "Error",
									JOptionPane.ERROR_MESSAGE);
						}
					}
				}
			}
		});

		btnSave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (textField_saleId.getText().isEmpty()) {
					JOptionPane.showMessageDialog(null, "Please select a sale",
							"Error", JOptionPane.ERROR_MESSAGE);
				} else {
					try {
						// TODO
						// set sale info
						int saleId = Integer.parseInt(textField_saleId.getText());
						Sale sale = new Sale();
						sale.setId(saleId);
						sale.setPayStatus(KeyWord
								.valueOf(listStringsSale[jcbsalePayStatus
										.getSelectedIndex()]));

						if (!textField_saleCreateDate.getText().isEmpty())
							sale.setCreateDate(new SimpleDateFormat(
									"dd/MM/yyyy")
									.parse(textField_saleCreateDate.getText()));

						if (!textField_salePayDate.getText().isEmpty())
							sale.setPayDate(new SimpleDateFormat("dd/MM/yyyy")
									.parse(textField_salePayDate.getText()));

						if (jcbsalePayMethod.getSelectedIndex() != 0)
							sale.setPayMethod(KeyWord
									.valueOf(listStringsPayMethod[jcbsalePayMethod
											.getSelectedIndex()]));

						// check if employee exist
						sale.setEmployee(personCtr.getEmployee(Integer
								.parseInt(textField_employeeId.getText())));

						// check if guest exist
						sale.setGuest((Guest) personCtr.getGuest(Integer
								.parseInt(textField_guestId.getText())));

						// set room booking info
						RoomBooking rb = new RoomBooking();
						rb.setId(Integer.parseInt(textField_saleId.getText()));
						rb.setCreateDate(new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbCreateDate.getText()));
						rb.setPayStatus(KeyWord
								.valueOf(listStringsRB[jcbrbPayStatus
										.getSelectedIndex()]));
						if (!isAbleToEdit(saleId)) {
							RoomBooking oldRb = roomBookingCtr.getRoomBooking(saleId);
							if (oldRb.getStartDate().equals(new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbStartDate.getText()))&& oldRb.getEndDate().equals(new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbEndDate.getText()))) {
								
							} else {
								throw new RoomBookingException ("The start date and end date are not able change after rooms have been checked in");
							}
						}
						// check the date
						Date startDate = new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbStartDate.getText());
						Date endDate = new SimpleDateFormat("dd/MM/yyyy")
								.parse(textField_rbEndDate.getText());
						Date currentDate = Calendar.getInstance().getTime();
						Calendar c = Calendar.getInstance();
						c.setTime(currentDate);
						c.add(Calendar.DAY_OF_MONTH, -1);
						Date dateBefore = c.getTime();
						if (startDate.after(endDate)) {
							JOptionPane
									.showMessageDialog(
											null,
											"Input start date value should be before end date",
											"Error", JOptionPane.ERROR_MESSAGE);
						} else if (startDate.before(dateBefore)) {
							JOptionPane.showMessageDialog(null,
									"Input start date is before current date",
									"Error", JOptionPane.ERROR_MESSAGE);
						} else {
							rb.setStartDate(new SimpleDateFormat("dd/MM/yyyy")
							.parse(textField_rbStartDate.getText()));
							rb.setEndDate(new SimpleDateFormat("dd/MM/yyyy")
							.parse(textField_rbEndDate.getText()));
							// calculate rent
							int days = calculateDatesForRB();
							double rent = 0;
							if (roomBookingLines.size() != 0) {
								LinkedList<RoomBookingLine> lines = new LinkedList<RoomBookingLine>();
								Set<Integer> rtIds = roomBookingLines.keySet();
								for (Integer rtId : rtIds) {
									RoomBookingLine line = new RoomBookingLine();
									RoomType rt = rtCtr.getRoomType(rtId);
									line.setRoomBooking(new RoomBooking(Integer
											.parseInt(textField_saleId
													.getText())));
									line.setRoomType(rt);
									line.setQuantity(roomBookingLines.get(rtId));
									line.setTotalPrice(rt.getPricePerNight()
											* roomBookingLines.get(rtId) * days);// set
																					// price
									lines.add(line);
								}
								// add room booking line
								for (RoomBookingLine line : lines) {
									rent += line.getRoomType()
											.getPricePerNight()
											* line.getQuantity() * days;
								}
								// set roombookinglines
								rb.setLines(lines);
							}

							rb.setRent(rent);
							rb.setDeposit(rent * RoomBooking.getHalfRate());

							// set sale price and room booking
							sale.setTotalPrice(Double
									.parseDouble(textField_salePrice.getText()));
							sale.setRoomBooking(rb);
							Sale oldSale = saleCtr.getSale(Integer
									.parseInt(textField_saleId.getText()));
							if (saleCtr.updateSale(oldSale, sale))
								JOptionPane.showMessageDialog(null,
										"The sale is updated", "Update Sale",
										JOptionPane.INFORMATION_MESSAGE);
							else
								JOptionPane
										.showMessageDialog(
												null,
												"Fail to create sale because of incorrect values",
												"Create Sale",
												JOptionPane.INFORMATION_MESSAGE);
						}
						cleanTextField();
						showAllSale();
					} catch (PersonException a) {
						JOptionPane.showMessageDialog(null,
								a.getPersonException(), "Error",
								JOptionPane.ERROR_MESSAGE);

					} catch (RoomBookingException a) {
						JOptionPane.showMessageDialog(null,
								a.getBookingException(), "Error",
								JOptionPane.ERROR_MESSAGE);

					} catch (SaleException d) {
						JOptionPane.showMessageDialog(null,
								d.getSaleException(), "Error",
								JOptionPane.ERROR_MESSAGE);
					} catch (ParseException e1) {
						JOptionPane.showMessageDialog(null,
								"Please input correct date format", "Error",
								JOptionPane.ERROR_MESSAGE);
					} catch (Exception f) {
						JOptionPane.showMessageDialog(null,
								"Please input correct values", "Error",
								JOptionPane.ERROR_MESSAGE);
					}
					showAllSale();
				}
			}
		});

		btnClear.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cleanTextField();
			}
		});
	}

	public boolean isAbleToEdit(int rbId) {
		boolean isAbleToEdit = true;
		RoomBooking rb = roomBookingCtr.getRoomBooking(rbId);
		LinkedList<RoomBookingLine> lines = rb.getLines();
		for (RoomBookingLine line : lines) {
			if (line.getRooms().size() != 0) {
				isAbleToEdit = false;
				return isAbleToEdit;
			}
		}
		return isAbleToEdit;
	}

	public void addRBTable() {
		rbTableModel = new DefaultTableModel();
		// rbTableModel.addColumn("Id");
		rbTableModel.addColumn("Room Type Id");
		rbTableModel.addColumn("Quantity");
		rbTableModel.addColumn("Rent");
		rbTableModel.addColumn("Check In Room Ids");
		// rbTableModel.addColumn("Check Out Room Ids");

		rbScrollPane = new JScrollPane();
		rbTable = new JTable(rbTableModel);
		rbTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
		rbTable.setAutoCreateRowSorter(true);

		rbTablePanel.add(rbScrollPane);
		rbScrollPane.setViewportView(rbTable);
	}

	public void showRBTable(int rbId) {
		rbTableModel.setRowCount(0);
		RoomBooking rb = roomBookingCtr.getRoomBooking(rbId);
		LinkedList<RoomBookingLine> lines = rb.getLines();

		// TODO assign room booking line to local object
		for (RoomBookingLine rbl : lines) {
			roomBookingLines.put(rbl.getRoomType().getId(), rbl.getQuantity());
		}

		for (RoomBookingLine line : lines) {
			String rooms = "";
			for (Room room : line.getRooms()) {
				rooms += room.getId() + ",";
			}
			rbTableModel.addRow(new Object[] { line.getRoomType().getId(),
					line.getQuantity(), line.getTotalPrice(), rooms });
		}

		String[] space = { "", "", "", "", "" };
		String[] totalPriceRow = { "", "Total Price:",
				String.valueOf(rb.getRent()), "", "" };
		rbTableModel.addRow(space);
		rbTableModel.addRow(space);
		rbTableModel.addRow(totalPriceRow);
	}

	public void showLineTable() {
		Set<Integer> rtIds = roomBookingLines.keySet();
		int days = 0;
		totalPrice = 0;

		Date startDate;
		Date endDate;
		try {
			startDate = new SimpleDateFormat("dd/MM/yyyy")
					.parse(textField_rbStartDate.getText());
			endDate = new SimpleDateFormat("dd/MM/yyyy")
					.parse(textField_rbEndDate.getText());

			if (startDate.after(endDate)) {
				JOptionPane.showMessageDialog(null,
						"Input start date value should be before end date",
						"Error", JOptionPane.ERROR_MESSAGE);
			} else {
				days = calculateDatesForRB();

				LinkedList<RoomType> slRoomTpes = new LinkedList<RoomType>();
				for (Integer rtId : rtIds) {
					slRoomTpes.add(rtCtr.getRoomType(rtId));
				}
				for (RoomType rt : slRoomTpes) {
					totalPrice += rt.getPricePerNight()
							* roomBookingLines.get(rt.getId()) * days;
				}

				rbTableModel.setRowCount(0);
				for (RoomType rt : slRoomTpes) {
					rbTableModel.addRow(new Object[] {
							rt.getId(),
							roomBookingLines.get(rt.getId()),
							rt.getPricePerNight()
									* roomBookingLines.get(rt.getId()) * days,
							"" });
				}
				String[] space = { "", "", "", "", "" };
				String[] totalPriceRow = { "", "Total Price:",
						String.valueOf(totalPrice), "", "" };
				rbTableModel.addRow(space);
				rbTableModel.addRow(space);
				rbTableModel.addRow(totalPriceRow);

				// set price to sale and rb field
				textField_rbRent.setText(Double.toString(totalPrice));
				textField_rbDeposit.setText(Double.toString(totalPrice / 2));
				textField_salePrice.setText(Double.toString(totalPrice));

			}
		} catch (ParseException e1) {
			JOptionPane.showMessageDialog(null,
					"Please input correct start date and end date value",
					"Error", JOptionPane.ERROR_MESSAGE);
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, e, "Error",
					JOptionPane.ERROR_MESSAGE);
		}

	}

	public void addSaleTable() {
		saleTableModel = new DefaultTableModel();
		saleTableModel.addColumn("Id");
		saleTableModel.addColumn("GuestId");
		saleTableModel.addColumn("EmployeeId");
		saleTableModel.addColumn("TotalPrice");

		saleScrollPane = new JScrollPane();
		saleTable = new JTable(saleTableModel);
		saleTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
		saleTable.setAutoCreateRowSorter(true);

		saleTable.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int row = saleTable.rowAtPoint(e.getPoint());
				if (e.getClickCount() == 1) {
					showSale(Integer.valueOf((Integer) saleTable.getValueAt(
							row, 0)));
				}
			}
		});

		allSalePanel.add(saleScrollPane, BorderLayout.CENTER);
		saleScrollPane.setViewportView(saleTable);
		saleTable.setPreferredScrollableViewportSize(new Dimension(100, 200));
	}

	public void showSale(int saleId) {
		try {
			cleanTextField();
			Sale sale = saleCtr.getSale(saleId);
			textField_saleId.setText(Integer.toString(sale.getId()));
			textField_guestId
					.setText(Integer.toString(sale.getGuest().getID()));
			textField_employeeId.setText(Integer.toString(sale.getEmployee()
					.getID()));
			textField_saleCreateDate.setText(new SimpleDateFormat("dd/MM/yyyy")
					.format(sale.getCreateDate()));
			if (sale.getPayDate() != null)
				textField_salePayDate
						.setText(new SimpleDateFormat("dd/MM/yyyy").format(sale
								.getPayDate()));
			if (sale.getPayMethod() != null)
				selectSalePayMethod(sale.getPayMethod());
			else
				jcbsalePayMethod.setSelectedIndex(0);
			selectSalePayStatus(sale.getPayStatus());
			textField_salePrice.setText(Double.toString(sale.getTotalPrice()));

			// show roombooking info
			RoomBooking rb = sale.getRoomBooking();
			if (rb != null) {
				textField_rbCreateDate.setText(new SimpleDateFormat(
						"dd/MM/yyyy").format(rb.getCreateDate()));
				textField_rbDeposit.setText(Double.toString(rb.getDeposit()));
				selectRBPayStatus(rb.getPayStatus());
				textField_rbEndDate.setText(new SimpleDateFormat("dd/MM/yyyy")
						.format(rb.getEndDate()));
				textField_rbStartDate
						.setText(new SimpleDateFormat("dd/MM/yyyy").format(rb
								.getStartDate()));
				textField_rbRent.setText(Double.toString(rb.getRent()));
				showRBTable(saleId);
			}
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, e, "Error",
					JOptionPane.ERROR_MESSAGE);
		}
	}

	public void showAllSale() {
		String searchFilter = search.getText();
		saleTableModel.setRowCount(0);
		LinkedList<Sale> sales = saleCtr.getAllSale();

		for (Sale sale : sales) {
			if (((Integer) sale.getId()).toString().toLowerCase()
					.contains(searchFilter.toLowerCase())
					|| ((Integer) sale.getGuest().getID()).toString()
							.toLowerCase().contains(searchFilter.toLowerCase())
					|| ((Integer) sale.getEmployee().getID()).toString()
							.toLowerCase().contains(searchFilter.toLowerCase())) {
				saleTableModel.addRow(new Object[] { sale.getId(),
						sale.getGuest().getID(), sale.getEmployee().getID(),
						sale.getTotalPrice(), });
			}
		}
	}

	public JFrame addSalelinePopupWindow() {
		final JFrame addLinePupupWindow = new JFrame("Add Line");
		addLinePupupWindow.setSize(450, 100);
		addLinePupupWindow.setLocationRelativeTo(null);
		JLabel rtId = new JLabel("Room Type Id:");
		JLabel quantity = new JLabel("Quantity:");
		textField_rtId = new JTextField();
		textField_rtId.setColumns(8);
		textField_rtQuantity = new JTextField();
		textField_rtQuantity.setColumns(8);
		JButton btnAddLineOK = new JButton("OK");
		btnAddLineOK.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// read from product and append to hashmap products

				try {
					roomBookingLines.put(
							Integer.parseInt(textField_rtId.getText()),
							Integer.parseInt(textField_rtQuantity.getText()));

					showLineTable();
					addLinePupupWindow.dispose();
				} catch (NumberFormatException e1) {
					JOptionPane.showMessageDialog(null,
							"Please input correct room type id and quantity.",
							"Error", JOptionPane.ERROR_MESSAGE);
				} catch (Exception e1) {
					JOptionPane.showMessageDialog(null, e1, "Error",
							JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		JButton btnAddLineCancel = new JButton("Cancel");
		btnAddLineCancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				addLinePupupWindow.dispose();
			}
		});

		JPanel addLinePanel = new JPanel();
		addLinePanel.setLayout(new BoxLayout(addLinePanel, BoxLayout.Y_AXIS));
		JPanel addLineInfoPanel = new JPanel();
		addLineInfoPanel.setLayout(new FlowLayout());
		JPanel addLineChoicePanel = new JPanel();
		addLineChoicePanel.setLayout(new FlowLayout());

		addLinePupupWindow.getContentPane().add(addLinePanel);
		addLinePanel.add(addLineInfoPanel);
		addLinePanel.add(addLineChoicePanel);
		addLineInfoPanel.add(rtId);
		addLineInfoPanel.add(textField_rtId);
		addLineInfoPanel.add(quantity);
		addLineInfoPanel.add(textField_rtQuantity);
		addLineChoicePanel.add(btnAddLineOK);
		addLineChoicePanel.add(btnAddLineCancel);

		return addLinePupupWindow;
	}

	private JFrame deleteSalelinePopupWindow() {
		final JFrame deleteLineWindow = new JFrame("Delete SaleLine");
		deleteLineWindow.setSize(500, 100);
		deleteLineWindow.setLocationRelativeTo(null);
		JLabel productBarcode = new JLabel("Room Type Id:");
		textField_rtId = new JTextField();
		textField_rtId.setColumns(8);
		JButton btnDeleteLineOK = new JButton("OK");
		btnDeleteLineOK.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// delete in hashmap products and retrieve product
				try {
					roomBookingLines.remove(Integer.parseInt(textField_rtId
							.getText()));

					showLineTable();
					deleteLineWindow.dispose();
				} catch (Exception e1) {
					JOptionPane.showMessageDialog(null, e1, "Error",
							JOptionPane.ERROR_MESSAGE);
				}

			}
		});
		JButton btnDeleteLineCancel = new JButton("Cancel");
		btnDeleteLineCancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				deleteLineWindow.dispose();
			}
		});
		JPanel deleteLinePanel = new JPanel();
		JPanel deleteLineInfoPanel = new JPanel();
		JPanel deleteLineChoicePanel = new JPanel();

		deleteLinePanel.setLayout(new BoxLayout(deleteLinePanel,
				BoxLayout.Y_AXIS));
		deleteLineInfoPanel.setLayout(new FlowLayout());
		deleteLineChoicePanel.setLayout(new FlowLayout());

		deleteLineWindow.getContentPane().add(deleteLinePanel);
		deleteLinePanel.add(deleteLineInfoPanel);
		deleteLinePanel.add(deleteLineChoicePanel);
		deleteLineInfoPanel.add(productBarcode);
		deleteLineInfoPanel.add(textField_rtId);
		deleteLineChoicePanel.add(btnDeleteLineOK);
		deleteLineChoicePanel.add(btnDeleteLineCancel);

		return deleteLineWindow;
	}

	public void cleanTextField() {
		totalPrice = 0;
		roomBookingLines = new HashMap<Integer, Integer>();
		rbTableModel.setRowCount(0);
		textField_employeeId.setText("");
		textField_guestId.setText("");
		textField_rbCreateDate.setText(new SimpleDateFormat("dd/MM/yyyy")
				.format(Calendar.getInstance().getTime()));
		textField_rbDeposit.setText("");
		textField_rbEndDate.setText("");
		textField_rbPayStatus.setText("");
		textField_rbRent.setText("");
		textField_rbStartDate.setText("");
		textField_saleCreateDate.setText(new SimpleDateFormat("dd/MM/yyyy")
				.format(Calendar.getInstance().getTime()));
		textField_saleId.setText("");
		textField_salePayDate.setText("");
		textField_salePayMethod.setText("");
		textField_salePayStatus.setText("");
		textField_salePrice.setText("");
	}

	public int calculateDatesForRB() {
		Date startDate;
		Date endDate;
		Calendar cal1 = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();
		try {
			startDate = new SimpleDateFormat("dd/MM/yyyy")
					.parse(textField_rbStartDate.getText());
			endDate = new SimpleDateFormat("dd/MM/yyyy")
					.parse(textField_rbEndDate.getText());
			cal1.setTime(startDate);
			cal2.setTime(endDate);

		} catch (ParseException e) {
			e.printStackTrace();
		}

		return daysBetween(cal1, cal2);
	}

	public int daysBetween(Calendar startDate, Calendar endDate) {
		Calendar date = (Calendar) startDate.clone();
		int daysBetween = 0;
		while (date.before(endDate)) {
			date.add(Calendar.DAY_OF_MONTH, 1);
			daysBetween++;
		}
		return daysBetween + 1;
	}

	@Override
	public void actionPerformed(ActionEvent e) {

	}

	public void selectSalePayMethod(KeyWord type) {
		if (type == KeyWord.CreditCard)
			jcbsalePayMethod.setSelectedIndex(1);
		else if (type == KeyWord.Cash)
			jcbsalePayMethod.setSelectedIndex(2);
	}

	public void selectSalePayStatus(KeyWord type) {
		if (type == KeyWord.SaleUnpaid)
			jcbsalePayStatus.setSelectedIndex(0);
		else if (type == KeyWord.SalePaid)
			jcbsalePayStatus.setSelectedIndex(1);
	}

	public void selectRBPayStatus(KeyWord type) {
		if (type == KeyWord.DepositUnpaid)
			jcbrbPayStatus.setSelectedIndex(0);
		else if (type == KeyWord.DepositPaid)
			jcbrbPayStatus.setSelectedIndex(1);
		else if (type == KeyWord.RentPaid)
			jcbrbPayStatus.setSelectedIndex(2);
	}
}
